package per.ethan.cloud.common.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.http.HttpStatus;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import per.ethan.cloud.common.domain.ErrorCodeVO;
import per.ethan.cloud.common.domain.Page;
import per.ethan.cloud.common.entity.BaseEntity;
import per.ethan.cloud.common.exception.ServiceException;
import per.ethan.cloud.common.mapper.BaseMapper;
import per.ethan.cloud.common.property.StateEnum;
import per.ethan.cloud.common.service.BaseService;
import per.ethan.cloud.common.util.SnowFlakeId;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author Ethan
 * @date 2020/03/10 19:57
 */
@Slf4j
@Service
public abstract class BaseServiceImpl<Entity extends BaseEntity> implements BaseService<Entity> {

    @Autowired
    private SnowFlakeId snowFlake;

    protected abstract BaseMapper<Entity> getBaseMapper();

    /**
     * 分页查询
     */
    @Override
    @Transactional(readOnly = true)
    public Page<Entity> findByPage(Page<Entity> page) {
        if (page.getStartRowNum() >= page.getEndRowNum()) {
            throw new ServiceException(new ErrorCodeVO(HttpStatus.HTTP_INTERNAL_ERROR, "分页查询时开始行必须小于结束行"));
        }
        //单页查询不允许超过500条，防止恶意调用page size过大导致内存溢出
        if (page.getPageSize() > Page.MAX_PAGE_SIZE) {
            throw new ServiceException(new ErrorCodeVO(HttpStatus.HTTP_INTERNAL_ERROR, "超过允许查询的单页记录最大值"));
        }
        try {
            Map<String, Object> queryParams = new HashMap<>(4);
            Map<String, Object> conditions = page.getConditions();

            if (CollUtil.isNotEmpty(conditions)) {
                queryParams.putAll(conditions);
            }
            queryParams.put("startRowNum", page.getStartRowNum());
            queryParams.put("endRowNum", page.getEndRowNum());
            queryParams.put("pageSize", page.getPageSize());
            queryParams.put("orderFields", page.getOrderFields());

            List<Entity> rows = this.getBaseMapper().findByPage(queryParams);

            page.setRows(rows);

            Integer count = this.getBaseMapper().getCount(queryParams);

            page.setTotal(count);
        } catch (Exception e) {
            throw e;
        }

        return page;
    }

    /**
     * 实现新增
     */
    @Transactional(rollbackFor = {Exception.class})
    @Override
    public Long save(Entity entity) {
        Long id = snowFlake.nextId();

        try {
            if (null == entity.getId()) {
                entity.setId(id);
            }
            entity.setState(StateEnum.NORMAL.getCode())
                    .setCreateDate(new Date());
            this.getBaseMapper().save(entity);
        } catch (Exception e) {
            throw e;
        }

        return entity.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<Long> batchSave(List<Entity> entities) {
        List<Long> ids = CollUtil.newArrayList();
        entities.forEach(entity -> {
            entity.setId(snowFlake.nextId())
                    .setCreateDate(new Date())
                    .setState(StateEnum.NORMAL.getCode());
            ids.add(entity.getId());
        });
        if (CollUtil.isEmpty(entities)) {
            throw new NullPointerException("不能存在ID为空的对象进行插入");
        }

        try {
            this.getBaseMapper().batchSave(entities);
        } catch (Exception e) {
            throw e;
        }

        return ids;
    }

    /**
     * 修改信息
     */
    @Transactional(rollbackFor = {Exception.class})
    @Override
    public boolean update(Entity entity) {
        try {
            if (entity.getId() == null) {
                throw new ServiceException(new ErrorCodeVO(HttpStatus.HTTP_INTERNAL_ERROR, "Id不允许为空!"));
            }

            this.getBaseMapper().update(entity);
        } catch (Exception e) {
            throw e;
        }

        return true;
    }


    @Transactional(rollbackFor = {Exception.class})
    @Override
    public boolean batchUpdate(Entity entity, List<String> idList) {
        try {
            if (entity == null || CollUtil.isEmpty(idList)) {
                throw new ServiceException(new ErrorCodeVO(HttpStatus.HTTP_INTERNAL_ERROR, "idList列表和Entity不允许为空!"));
            }

            Map<String, Object> params = BeanUtil.beanToMap(entity);
            ;
            params.put("idList", idList);

            this.getBaseMapper().batchUpdate(params);
        } catch (Exception e) {
            throw new ServiceException(new ErrorCodeVO(HttpStatus.HTTP_INTERNAL_ERROR, e.getMessage()));
        }

        return true;
    }

    /**
     * 通过条件删除
     *
     * @param map
     * @return
     * @throws ServiceException
     */
    @Transactional(rollbackFor = {Exception.class})
    @Override
    public boolean deleteByWhere(Map<String, Object> map) {
        try {
            this.getBaseMapper().deleteByWhere(map);
        } catch (Exception e) {
            throw e;
        }

        return true;
    }

    @Transactional(rollbackFor = {Exception.class})
    @Override
    public boolean logicDeleteByWhere(Map<String, Object> map) {
        try {
            this.getBaseMapper().logicDeleteByWhere(map);
        } catch (Exception e) {
            throw e;
        }

        return true;
    }

    /**
     * 通过id删除
     */
    @Transactional(rollbackFor = {Exception.class})
    @Override
    public boolean deleteById(Long id) {
        try {
            this.getBaseMapper().deleteById(id);
        } catch (Exception e) {
            throw e;
        }

        return true;
    }

    @Transactional(rollbackFor = {Exception.class})
    @Override
    public boolean logicDeleteById(Long id) {
        try {
            this.getBaseMapper().logicDeleteById(id);
        } catch (Exception e) {
            throw e;
        }

        return true;
    }

    /**
     * 批量删除
     */
    @Transactional(rollbackFor = {Exception.class})
    @Override
    public boolean batchDelete(List<Long> idList) {
        try {
            this.getBaseMapper().batchDelete(idList);
        } catch (Exception e) {
            throw e;
        }

        return true;
    }

    @Transactional(rollbackFor = {Exception.class})
    @Override
    public boolean logicBatchDelete(List<Long> idList) {
        try {
            this.getBaseMapper().logicBatchDelete(idList);
        } catch (Exception e) {
            throw e;
        }

        return true;
    }

    /**
     * 通过id查询
     */
    @Override
    @Transactional(readOnly = true)
    public Entity findById(Long id) {
        Entity entity;

        try {
            entity = this.getBaseMapper().findById(id);
        } catch (Exception e) {
            throw e;
        }

        return entity;
    }

    @Override
    @Transactional(readOnly = true)
    public Entity findByName(String name) {
        Entity entity;

        try {
            entity = this.getBaseMapper().findByName(name);
        } catch (Exception e) {
            throw e;
        }

        return entity;
    }

    /**
     * 查询所有信息
     */
    @Override
    @Transactional(readOnly = true)
    public List<Entity> findAll() {
        List<Entity> list;

        try {
            list = this.getBaseMapper().findAll();
        } catch (Exception e) {
            throw e;
        }

        return list;
    }

    /**
     * 根据不同的条件查询
     */
    @Override
    @Transactional(readOnly = true)
    public List<Entity> findByMap(Map<String, Object> map) {
        List<Entity> list;

        try {
            list = this.getBaseMapper().findByMap(map);
        } catch (Exception e) {
            throw e;
        }

        return list;
    }

}
